package com.itcam.cloud.controller;

import cn.hutool.core.util.IdUtil;
import com.itcam.cloud.apis.PayFeignApi;
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@RestController
public class OrderCircuitController {
    @Resource
    private PayFeignApi payFeignApi;

    @GetMapping(value = "/feign/pay/circuit/{id}")
    @CircuitBreaker(name = "cloud-payment-service", fallbackMethod = "myCircuitFallback")
    public String myCircuitBreaker(@PathVariable("id") Integer id) {
        return payFeignApi.myCircuit(id);
    }

    //myCircuitFallback就是服务降级后的兜底处理方法
    public String myCircuitFallback(Integer id, Throwable t) {
        // 这里是容错处理逻辑，返回备用结果
        return "myCircuitFallback，系统繁忙，请稍后再试-----/(ㄒoㄒ)/~~";
    }

    // ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

    /**
     * (船的)舱壁,隔离
     * @param id 用于标识请求的唯一 ID
     * @return 调用 payFeignApi.myBulkhead 方法返回的结果
     */
//    @GetMapping(value = "/feign/pay/bulkhead/{id}")
//    @Bulkhead(name = "cloud-payment-service", fallbackMethod = "myBulkheadFallback", type = Bulkhead.Type.SEMAPHORE)
//    public String myBulkhead(@PathVariable("id") Integer id) {
//        // 调用 payFeignApi 的 myBulkhead 方法，并传入 id 参数
//        return payFeignApi.myBulkhead(id);
//    }
//
//    /**
//     * 当 myBulkhead 方法触发舱壁保护时的回调方法
//     * @param t 触发回调的异常信息
//     * @return 提示信息，告知隔板超出最大数量限制，系统繁忙
//     */
//    public String myBulkheadFallback(Throwable t) {
//        // 返回提示信息，告知隔板超出最大数量限制，系统繁忙
//        return "myBulkheadFallback，隔板超出最大数量限制，系统繁忙，请稍后再试-----/(ㄒoㄒ)/~~";
//    }

    // ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

    /**
     * (船的)舱壁,隔离,THREADPOOL
     * 此方法使用线程池类型的舱壁隔离机制处理请求。
     * 当请求进入时，会打印进入信息，模拟耗时操作，然后打印退出信息。
     * 若请求成功，将调用 payFeignApi 的 myBulkhead 方法并返回结果。
     * 若触发舱壁保护，将调用 myBulkheadPoolFallback 方法进行降级处理。
     *
     * @param id 用于标识请求的唯一 ID
     * @return 一个 CompletableFuture 对象，包含调用 payFeignApi.myBulkhead 方法的结果，
     *         并附加 " Bulkhead.Type.THREADPOOL" 字符串
     */
    @GetMapping(value = "/feign/pay/bulkhead/{id}")
    @Bulkhead(name = "cloud-payment-service", fallbackMethod = "myBulkheadPoolFallback", type = Bulkhead.Type.THREADPOOL)
    public CompletableFuture<String> myBulkheadTHREADPOOL(@PathVariable("id") Integer id) {
        // 打印当前线程名称和进入方法的信息
        System.out.println(Thread.currentThread().getName() + "\t" + "enter the method!!!");
        try {
            // 模拟耗时操作，线程休眠 3 秒
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            // 打印异常堆栈信息
            e.printStackTrace();
        }
        // 打印当前线程名称和退出方法的信息
        System.out.println(Thread.currentThread().getName() + "\t" + "exist the method!!!");

        // 异步执行 payFeignApi.myBulkhead 方法，并返回结果
        return CompletableFuture.supplyAsync(() -> payFeignApi.myBulkhead(id) + "\t" + " Bulkhead.Type.THREADPOOL");
    }

    /**
     * 当 myBulkheadTHREADPOOL 方法触发舱壁保护时的回调方法。
     * 此方法返回一个 CompletableFuture 对象，包含提示信息，告知系统繁忙，建议用户稍后再试。
     *
     * @param id 用于标识请求的唯一 ID
     * @param t 触发回调的异常信息
     * @return 一个 CompletableFuture 对象，包含提示信息 "Bulkhead.Type.THREADPOOL，系统繁忙，请稍后再试-----/(ㄒoㄒ)/~~"
     */
    public CompletableFuture<String> myBulkheadPoolFallback(Integer id, Throwable t) {
        // 异步返回提示信息
        return CompletableFuture.supplyAsync(() -> "Bulkhead.Type.THREADPOOL，系统繁忙，请稍后再试-----/(ㄒoㄒ)/~~");
    }

    //=========Resilience4j ratelimit 的例子
    @GetMapping(value = "/pay/ratelimit/{id}")
    public String myRatelimit(@PathVariable("id") Integer id) {
        return "Hello, myRatelimit欢迎到来 inputId:  " + id + " \t " + IdUtil.simpleUUID();
    }

    // ——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

    /**
     * 该方法用于处理针对 "/feign/pay/ratelimit/{id}" 的 GET 请求，并应用了限流策略。
     * 当客户端访问该接口时，会根据配置的限流规则进行检查。
     * 如果请求未超过限流阈值，则调用 payFeignApi 的 myRatelimit 方法处理请求。
     * 如果请求超过限流阈值，会触发限流，调用 myRatelimitFallback 方法进行降级处理。
     *
     * @param id 用于标识请求的唯一 ID，通过路径参数传递
     * @return 调用 payFeignApi.myRatelimit 方法的返回结果
     */
    @GetMapping(value = "/feign/pay/ratelimit/{id}")
    @RateLimiter(name = "cloud-payment-service", fallbackMethod = "myRatelimitFallback")
    public String myBulkhead(@PathVariable("id") Integer id) {
        // 调用 payFeignApi 的 myRatelimit 方法处理请求
        return payFeignApi.myRatelimit(id);
    }

    /**
     * 当 myBulkhead 方法触发限流时的回调方法。
     * 此方法会在请求超过限流阈值时被调用，用于返回提示信息给客户端。
     *
     * @param id 用于标识请求的唯一 ID
     * @param t 触发回调的异常信息
     * @return 提示信息，告知客户端被限流，禁止访问
     */
    public String myRatelimitFallback(Integer id, Throwable t) {
        // 返回提示信息，告知客户端被限流
        return "你被限流了，禁止访问/(ㄒoㄒ)/~~";
    }


}